//MountManager - the program for easy mounting of storage devices in Linux
//Copyright (C) 2007-2008 Tikhonov Sergey
//
//This file is part of MountManager Gui
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#include <QtGui/QPushButton>
#include <QtGui/QLabel>
#include <QtGui/QCheckBox>
#include <QtGui/QLineEdit>
#include <QtGui/QComboBox>
#include <QtGui/QTableWidget>
#include <QtGui/QVBoxLayout>
#include <QtGui/QHBoxLayout>
#include <QtGui/QAction>
#include <QtGui/QSpinBox>
#include "../core/diskdevice.h"
#include "../core/diskcore.h"
#include "volumewidget.h"
#include "optionsview.h"
#include "infobutton.h"
#include "choosemountpointwidget.h"
#include "const.h"


VolumeWidget::VolumeWidget(DiskCore *core,DiskDevice *dev,PopupWindow *popup) {
	device = dev;

	changeMountPointAction = new QAction(this);
	changeMountPointAction->setText(tr("Change mount point"));

	optionsView = new OptionsView(dev,popup);
	
	if (device->isSupportDvd()) {
		udfOrIsoComboBox = new QComboBox;
		udfOrIsoComboBox->addItem(tr("DVD and CD together"),"udf,iso9660");
		udfOrIsoComboBox->addItem(tr("Only DVD"),"udf");
		udfOrIsoComboBox->addItem(tr("Only CD"),"iso9660");
		connect(udfOrIsoComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(udfOrIsoChangedSlot(int)));
		udfOrIsoLabel = new QLabel(tr("What kind of disks do you use?"));
	} else {
		udfOrIsoComboBox = 0;
		udfOrIsoLabel = 0;
	}

	showDefaultOptions = new QCheckBox(tr("Show default options"));

	mountPointLine = new ChooseMountPointWidget;
	mountPointLine->setMountPoint(device->currentMountPoint());
	if (!mountPointLine->isValid())
		mountPointLine->setMountPoint(device->fstabMountPoint());

	dump = new QCheckBox(tr("Use the program \"Dump\" for system restoration"));
	fsck = new QSpinBox;
	fsck->setMaximum(2);
	fsck->setMinimum(0);

	dump->setChecked(device->dump());
	fsck->setValue(device->fsck());
	
	optionsLine = new QLineEdit;
	optionsLine->setReadOnly(true);
	optionsLineInfoButton = new InfoButton(popup);
	optionsLineInfoButton->setPopupText(tr("This line will be written to configuration file. When the Linux system mount the partition, it will mount with these options."));
	optionsLineInfoButton->setPopupHeaderText(tr("Options line"));

	optionsView->addOptions(core->fileSystemOptions("common"),"common");
	
	if (device->type() == "cdrom") {
		optionsView->addOptions(core->fileSystemOptions("iso9660"),"iso9660");
		if (device->isSupportDvd())
			optionsView->addOptions(core->fileSystemOptions("udf"),"udf");
	} else
		optionsView->addOptions(core->fileSystemOptions(device->fileSystem()),device->fileSystem());

	if (device->fileSystem() == "ntfs") {
		useNtfs3gOptions = new QCheckBox(tr("Use special program for work with ntfs file system \"ntfs-3g\""));
		optionsView->addOptions(core->fileSystemOptions("ntfs-3g"),"ntfs-3g");

		useNtfs3gOptions->setChecked(device->fstabFileSystem() == "ntfs-3g");
		useNtfs3g(device->fstabFileSystem() == "ntfs-3g");
	} else
		useNtfs3gOptions = 0;
	
	QVBoxLayout *mainLayout = new QVBoxLayout;
	
	QHBoxLayout *optionsLayout = new QHBoxLayout;
	optionsLayout->addWidget(new QLabel(tr("Options") + ":"));
	optionsLayout->addWidget(optionsLine,1);
	optionsLayout->addWidget(optionsLineInfoButton);

	if (udfOrIsoLabel) {
		QHBoxLayout *udfOrIsoLayout = new QHBoxLayout;
		udfOrIsoLayout->addWidget(udfOrIsoLabel);
		udfOrIsoLayout->addWidget(udfOrIsoComboBox);
		udfOrIsoLayout->addStretch();
		mainLayout->addLayout(udfOrIsoLayout);
	}
	
	if (useNtfs3gOptions)
		mainLayout->addWidget(useNtfs3gOptions);

	QHBoxLayout *mountPointLayout = new QHBoxLayout;
	mountPointLayout->addWidget(new QLabel(tr("Mount point") + ":"));
	mountPointLayout->addWidget(mountPointLine);
	mountPointLayout->addStretch();

	QHBoxLayout *dumpLayout = new QHBoxLayout;
	dumpLayout->addWidget(dump);
	dumpLayout->addStretch();

	QHBoxLayout *fsckLayout = new QHBoxLayout;
	fsckLayout->addWidget(new QLabel(tr("Value of the program \"Fsck\"") + ":"));
	fsckLayout->addWidget(fsck);
	fsckLayout->addStretch();

	mainLayout->addLayout(mountPointLayout);
	mainLayout->addLayout(dumpLayout);
	mainLayout->addLayout(fsckLayout);
	mainLayout->addWidget(new QLabel("<hr>"));
	
	QVBoxLayout *boxLayout = new QVBoxLayout;
	boxLayout->addWidget(showDefaultOptions);
	boxLayout->addLayout(optionsLayout);
	boxLayout->addWidget(optionsView);
	
	mainLayout->addLayout(boxLayout);
	setLayout(mainLayout);

	connect(optionsView,SIGNAL(optionChanged()),this,SLOT(updateOptionLine()));
	connect(optionsView,SIGNAL(optionChanged()),this,SIGNAL(optionsChanged()));
	connect(showDefaultOptions,SIGNAL(clicked()),this,SLOT(updateOptionLine()));
	if (useNtfs3gOptions)
		connect(useNtfs3gOptions,SIGNAL(toggled(bool)),this,SLOT(useNtfs3g(bool)));
	connect(device,SIGNAL(currentMountPointChanged(const QString &)),this,SLOT(setMountPoint(const QString &)));

	
	if (udfOrIsoComboBox) {
		if (!device->fstabFileSystem().isEmpty()) {
			if (device->fstabFileSystem() == "udf,iso9660")
				udfOrIsoChangedSlot(0);
			else if (device->fstabFileSystem() == "udf")
				udfOrIsoComboBox->setCurrentIndex(1);
			else if (device->fstabFileSystem() == "iso9660")
				udfOrIsoComboBox->setCurrentIndex(2);
		} else
			udfOrIsoChangedSlot(0);
	}

	updateOptionLine();
}

VolumeWidget::~VolumeWidget() {
	delete showDefaultOptions;
	delete changeMountPointAction;
	delete mountPointLine;
	delete dump;
	delete fsck;

	delete optionsLine;
	delete optionsLineInfoButton;

	delete optionsView;
}

void VolumeWidget::updateOptionLine() {
	QString optionLineText = optionsView->getOptions(showDefaultOptions->isChecked());
	
	// rw,suid,dev,exec,auto,nouser,async == defaults
	if (!showDefaultOptions->isChecked())
		replaceDefaultOptionsOnOneWord(optionLineText);
	// If first character of option line is comma remove it
	if (!optionLineText.isEmpty() && optionLineText[0] == ',')
		optionLineText.remove(0,1);
	// If last character of option line is comma remove it
	if (!optionLineText.isEmpty() && optionLineText[optionLineText.length()-1] == ',')
		optionLineText.remove(optionLineText.length()-1,1);
	// If option line is empty then all options are default
	if (optionLineText.isEmpty())
		optionLineText = tr("All options are default");
	optionsLine->setText(optionLineText);
}

void VolumeWidget::replaceDefaultOptionsOnOneWord(QString& options) {
	if (options.contains("rw") && options.contains("suid") && options.contains("dev") && options.contains("exec")
		&& options.contains("auto") && options.contains("nouser") && options.contains("async")) {
		options = options.remove("rw,");
		options = options.remove("suid,");
		options = options.remove("dev,");
		options = options.remove("exec,");
		options = options.remove("auto,");
		options = options.remove("nouser,");
		options = options.remove("async,");
		options += ",defaults";
	}
}

void VolumeWidget::udfOrIsoChangedSlot(int index) {
	switch (index) {
		case 0:
			optionsView->showOptions(QList<int>() << OptionsView::General);
			break;
		case 1:
			optionsView->showOptions(QList<int>() << OptionsView::General << OptionsView::Udf);
			break;
		case 2:
			optionsView->showOptions(QList<int>() << OptionsView::General << OptionsView::Iso);
			break;
	}
	updateOptionLine();
}

void VolumeWidget::useNtfs3g(bool use) {
	if (use)
		optionsView->showOptions(QList<int>() << OptionsView::Ntfs3g);
	else 
		optionsView->showOptions(QList<int>() << OptionsView::General << OptionsView::Advanced);
	updateOptionLine();
	
}

const QString& VolumeWidget::mountPoint() const {
	return mountPointLine->mountPoint();
}

QString VolumeWidget::options() {
	return optionsView->getOptions(false).isEmpty() ? "defaults" : optionsView->getOptions(false);
}

void VolumeWidget::setMountPoint(const QString &mountPoint) {
	if (mountPoint.isEmpty())
		mountPointLine->setMountPoint(device->fstabMountPoint());
	else
		mountPointLine->setMountPoint(mountPoint);
}

QString VolumeWidget::fileSystem() {
	if (useNtfs3gOptions && useNtfs3gOptions->isChecked())
		return "ntfs-3g";
	else if (udfOrIsoComboBox)
		return udfOrIsoComboBox->itemData(udfOrIsoComboBox->currentIndex()).toString();
	return device->fileSystem();
}

QString VolumeWidget::fstabLine(bool warn,const QString& format) {
	QString mainLine;
	if (format == "name")
		mainLine += device->blockName() + '\t';
	else if (format == "uuid")
		if (device->uuid().isEmpty())
			mainLine += device->blockName() + '\t';
		else
			mainLine += "UUID=" + device->uuid() + '\t';
	else if (format == "label") {
		if (device->label().isEmpty()) {
			if (device->uuid().isEmpty())
				mainLine += device->blockName() + '\t';
			else
				mainLine += "UUID=" + device->uuid() + '\t';
		} else
			mainLine += "LABEL=" + device->label() + '\t';
	}
	if (!mountPointLine->isValid() && warn) {
		emit (showWarning(tr("Mount point for device %1 is empty - in configuration file this device will skip.").arg(device->blockName()),QList<QAction *>() << changeMountPointAction));
		return QString();
	} else
		mainLine += mountPointLine->mountPoint() + '\t';
	mainLine += fileSystem() + '\t';
	QString opts = options();
	mainLine += opts.isEmpty() ? "defaults" : opts;
	mainLine += '\t';
	mainLine += dump->isChecked() ? "1" : "0";
	mainLine += '\t';
	mainLine += QVariant(fsck->value()).toString();
	
	return mainLine;
}
